package com.py.credit.utils;

import com.py.credit.utils.ByteUtil;
import com.py.credit.utils.DateTimeUtil;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x9.X9ECParameters;

import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jcajce.spec.SM2ParameterSpec;
import org.bouncycastle.jce.X509KeyUsage;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;

import org.bouncycastle.util.encoders.Hex;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.security.auth.x500.X500Principal;
import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.ECPrivateKey;
import java.util.Arrays;
import java.util.Date;

public class GMUtil {
    private static X9ECParameters x9ECParameters = GMNamedCurves.getByName("sm2p256v1");
    private static ECDomainParameters ecDomainParameters;
    private static ECParameterSpec ecParameterSpec;
    private static final int RS_LEN = 32;
    private static final BigInteger p;
    private static final BigInteger a;
    private static final BigInteger b;
    private static final BigInteger xg;
    private static final BigInteger yg;
    private static final BigInteger n;
    private static SecureRandom random;

    public static byte[] signSm3WithSm2(byte[] msg, byte[] userId, PrivateKey privateKey) {
        return rsAsn1ToPlainByteArray(signSm3WithSm2Asn1Rs(msg, userId, privateKey));
    }

    public static byte[] signSm3WithSm2Asn1Rs(byte[] msg, byte[] userId, PrivateKey privateKey) {
        try {
            SM2ParameterSpec parameterSpec = new SM2ParameterSpec(userId);
            Signature signer = Signature.getInstance("SM3withSM2", "BC");
            signer.setParameter(parameterSpec);
            signer.initSign(privateKey, new SecureRandom());
            signer.update(msg, 0, msg.length);
            byte[] sig = signer.sign();
            return sig;
        } catch (Exception var6) {
            throw new RuntimeException(var6);
        }
    }

    public static boolean verifySm3WithSm2(byte[] msg, byte[] userId, byte[] rs, PublicKey publicKey) {
        return verifySm3WithSm2Asn1Rs(msg, userId, rsPlainByteArrayToAsn1(rs), publicKey);
    }

    public static boolean verifySm3WithSm2Asn1Rs(byte[] msg, byte[] userId, byte[] rs, PublicKey publicKey) {
        try {
            SM2ParameterSpec parameterSpec = new SM2ParameterSpec(userId);
            Signature verifier = Signature.getInstance("SM3withSM2", "BC");
            verifier.setParameter(parameterSpec);
            verifier.initVerify(publicKey);
            verifier.update(msg, 0, msg.length);
            return verifier.verify(rs);
        } catch (Exception var6) {
            throw new RuntimeException(var6);
        }
    }

    public static byte[] changeC1C2C3ToC1C3C2(byte[] c1c2c3) {
        int c1Len = (x9ECParameters.getCurve().getFieldSize() + 7) / 8 * 2 + 1;
        boolean c3Len = true;
        byte[] result = new byte[c1c2c3.length];
        System.arraycopy(c1c2c3, 0, result, 0, c1Len);
        System.arraycopy(c1c2c3, c1c2c3.length - 32, result, c1Len, 32);
        System.arraycopy(c1c2c3, c1Len, result, c1Len + 32, c1c2c3.length - c1Len - 32);
        return result;
    }

    public static byte[] changeC1C3C2ToC1C2C3(byte[] c1c3c2) {
        int c1Len = (x9ECParameters.getCurve().getFieldSize() + 7) / 8 * 2 + 1;
        boolean c3Len = true;
        byte[] result = new byte[c1c3c2.length];
        System.arraycopy(c1c3c2, 0, result, 0, c1Len);
        System.arraycopy(c1c3c2, c1Len + 32, result, c1Len, c1c3c2.length - c1Len - 32);
        System.arraycopy(c1c3c2, c1Len, result, c1c3c2.length - 32, 32);
        return result;
    }

    public static byte[] sm2Decrypt(byte[] data, PrivateKey key) {
        return sm2DecryptOld(changeC1C3C2ToC1C2C3(data), key);
    }

    public static byte[] sm2Encrypt(byte[] data, PublicKey key) {
        return changeC1C2C3ToC1C3C2(sm2EncryptOld(data, key));
    }

    public static byte[] sm2EncryptOld(byte[] data, PublicKey key) {
        BCECPublicKey localECPublicKey = (BCECPublicKey)key;
        ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(localECPublicKey.getQ(), ecDomainParameters);
        SM2Engine sm2Engine = new SM2Engine();
        sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom()));

        try {
            return sm2Engine.processBlock(data, 0, data.length);
        } catch (InvalidCipherTextException var6) {
            throw new RuntimeException(var6);
        }
    }

    public static byte[] sm2DecryptOld(byte[] data, PrivateKey key) {
        BCECPrivateKey localECPrivateKey = (BCECPrivateKey)key;
        ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(localECPrivateKey.getD(), ecDomainParameters);
        SM2Engine sm2Engine = new SM2Engine();
        sm2Engine.init(false, ecPrivateKeyParameters);

        try {
            return sm2Engine.processBlock(data, 0, data.length);
        } catch (InvalidCipherTextException var6) {
            throw new RuntimeException(var6);
        }
    }

    public static byte[] sm4Encrypt(byte[] keyBytes, byte[] plain) {
        byte[] keyBytes0;
        if (keyBytes.length != 16) {
            keyBytes0 = new byte[16];

            for(int i = 0; i < keyBytes0.length; ++i) {
                if (keyBytes.length > i) {
                    keyBytes0[i] = keyBytes[i];
                }
            }

            keyBytes = keyBytes0;
        }

        if (plain.length % 16 != 0) {
            keyBytes0 = new byte[16 * (plain.length / 16 + 1)];
            System.arraycopy(plain, 0, keyBytes0, 0, plain.length);
            plain = keyBytes0;
        }

        try {
            Key key = new SecretKeySpec(keyBytes, "SM4");
            Cipher out = Cipher.getInstance("SM4/ECB/NoPadding", "BC");
            out.init(1, key);
            return out.doFinal(plain);
        } catch (Exception var4) {
            throw new RuntimeException(var4);
        }
    }

    public static byte[] sm4Decrypt(byte[] keyBytes, byte[] cipher) {
        byte[] keyBytes0;
        if (keyBytes.length != 16) {
            keyBytes0 = new byte[16];

            for(int i = 0; i < keyBytes0.length; ++i) {
                if (keyBytes.length > i) {
                    keyBytes0[i] = keyBytes[i];
                }
            }

            keyBytes = keyBytes0;
        }

        if (cipher.length % 16 != 0) {
            keyBytes0 = new byte[16 * (cipher.length / 16 + 1)];
            System.arraycopy(cipher, 0, keyBytes0, 0, cipher.length);
            cipher = keyBytes0;
        }

        try {
            Key key = new SecretKeySpec(keyBytes, "SM4");
            Cipher in = Cipher.getInstance("SM4/ECB/NoPadding", "BC");
            in.init(2, key);
            byte[] bytes = in.doFinal(cipher);

            for(int i = bytes.length - 1; i >= 0; --i) {
                if (bytes[i] != 0) {
                    byte[] bytes1 = new byte[i + 1];
                    System.arraycopy(bytes, 0, bytes1, 0, i + 1);
                    bytes = bytes1;
                    i = -1;
                }
            }

            return bytes;
        } catch (Exception var7) {
            throw new RuntimeException(var7);
        }
    }

    public static String sm4Encrypt(String key, String plan) {
        byte[] keyBytes = new byte[16];
        byte[] keyBytes0 = new byte[0];

        try {
            keyBytes0 = key.getBytes("UTF-8");
        } catch (UnsupportedEncodingException var7) {
            var7.printStackTrace();
        }

        for(int i = 0; i < keyBytes.length; ++i) {
            if (keyBytes0.length > i) {
                keyBytes[i] = keyBytes0[i];
            }
        }

        byte[] cipher = new byte[0];

        try {
            cipher = plan.getBytes("UTF-8");
        } catch (UnsupportedEncodingException var6) {
            var6.printStackTrace();
        }

        byte[] bytes = sm4Encrypt(keyBytes, cipher);
        return Hex.toHexString(bytes).toUpperCase();
    }

    public static String sm4Decrypt(String key, String cipher) {
        byte[] keyBytes = new byte[16];
        byte[] keyBytes0 = new byte[0];

        try {
            keyBytes0 = key.getBytes("UTF-8");
        } catch (UnsupportedEncodingException var8) {
            var8.printStackTrace();
        }

        for(int i = 0; i < keyBytes.length; ++i) {
            if (keyBytes0.length > i) {
                keyBytes[i] = keyBytes0[i];
            }
        }

        byte[] cipherbytes = Hex.decode(cipher);
        byte[] bytes = sm4Decrypt(keyBytes, cipherbytes);

        try {
            return new String(bytes, "UTF-8");
        } catch (UnsupportedEncodingException var7) {
            var7.printStackTrace();
            return "";
        }
    }

    public static byte[] sm3(byte[] bytes) {
        SM3Digest sm3 = new SM3Digest();
        sm3.update(bytes, 0, bytes.length);
        byte[] result = new byte[sm3.getDigestSize()];
        sm3.doFinal(result, 0);
        return result;
    }

    public static String sm3(String str0) {
        SM3Digest sm3 = new SM3Digest();
        byte[] bytes = new byte[0];

        try {
            bytes = str0.getBytes("UTF-8");
        } catch (UnsupportedEncodingException var4) {
            var4.printStackTrace();
        }

        sm3.update(bytes, 0, bytes.length);
        byte[] result = new byte[sm3.getDigestSize()];
        sm3.doFinal(result, 0);
        return Hex.toHexString(result).toUpperCase();
    }

    private static byte[] bigIntToFixexLengthBytes(BigInteger rOrS) {
        byte[] rs = rOrS.toByteArray();
        if (rs.length == 32) {
            return rs;
        } else if (rs.length == 33 && rs[0] == 0) {
            return Arrays.copyOfRange(rs, 1, 33);
        } else if (rs.length < 32) {
            byte[] result = new byte[32];
            Arrays.fill(result, (byte)0);
            System.arraycopy(rs, 0, result, 32 - rs.length, rs.length);
            return result;
        } else {
            throw new RuntimeException("err rs: " + Hex.toHexString(rs));
        }
    }

    private static byte[] rsAsn1ToPlainByteArray(byte[] rsDer) {
        ASN1Sequence seq = ASN1Sequence.getInstance(rsDer);
        byte[] r = bigIntToFixexLengthBytes(ASN1Integer.getInstance(seq.getObjectAt(0)).getValue());
        byte[] s = bigIntToFixexLengthBytes(ASN1Integer.getInstance(seq.getObjectAt(1)).getValue());
        byte[] result = new byte[64];
        System.arraycopy(r, 0, result, 0, r.length);
        System.arraycopy(s, 0, result, 32, s.length);
        return result;
    }

    private static byte[] rsPlainByteArrayToAsn1(byte[] sign) {
        if (sign.length != 64) {
            throw new RuntimeException("err rs. ");
        } else {
            BigInteger r = new BigInteger(1, Arrays.copyOfRange(sign, 0, 32));
            BigInteger s = new BigInteger(1, Arrays.copyOfRange(sign, 32, 64));
            ASN1EncodableVector v = new ASN1EncodableVector();
            v.add(new ASN1Integer(r));
            v.add(new ASN1Integer(s));

            try {
                return (new DERSequence(v)).getEncoded("DER");
            } catch (IOException var5) {
                throw new RuntimeException(var5);
            }
        }
    }

    public static KeyPair generateKeyPair() {
        try {
            KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", "BC");
            kpGen.initialize(ecParameterSpec, new SecureRandom());
            KeyPair kp = kpGen.generateKeyPair();
            return kp;
        } catch (Exception var2) {
            return sm2generateKeyPair();
        }
    }

    public static KeyPair sm2generateKeyPair() {
        BigInteger max = n.subtract(new BigInteger("1"));

        BigInteger r;
        for(r = new BigInteger(256, random); r.compareTo(max) >= 0; r = new BigInteger(128, random)) {
            ;
        }

        ECCurve.Fp curve = new ECCurve.Fp(p, a, b);
        ECPoint G = curve.createPoint(xg, yg);
        String pubkey = ByteUtil.bytesToHexString(G.multiply(r).normalize().getEncoded(true));
        String prikey = ByteUtil.bytesToHexString(r.toByteArray());
        PublicKey publicKey0 = getPublickey(Hex.decode(pubkey));
        BCECPrivateKey privateKey0 = getPrivatekeyFromD(new BigInteger(prikey, 16));
        return new KeyPair(publicKey0, privateKey0);
    }

    public static BCECPrivateKey getPrivatekeyFromD(BigInteger d) {
        ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d, ecParameterSpec);
        return new BCECPrivateKey("EC", ecPrivateKeySpec, BouncyCastleProvider.CONFIGURATION);
    }

    public static BCECPublicKey getPublickeyFromXY(BigInteger x, BigInteger y) {
        ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(x9ECParameters.getCurve().createPoint(x, y), ecParameterSpec);
        return new BCECPublicKey("EC", ecPublicKeySpec, BouncyCastleProvider.CONFIGURATION);
    }

    public static BCECPublicKey getPublickey(byte[] pubkeybytes) {
        ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(x9ECParameters.getCurve().decodePoint(pubkeybytes), ecParameterSpec);
        return new BCECPublicKey("EC", ecPublicKeySpec, BouncyCastleProvider.CONFIGURATION);
    }

    public static PublicKey getPublickeyFromX509File(File file) {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
            FileInputStream in = new FileInputStream(file);
            X509Certificate x509 = (X509Certificate)cf.generateCertificate(in);
            return x509.getPublicKey();
        } catch (Exception var4) {
            throw new RuntimeException(var4);
        }
    }

    public static void main(String[] args) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, CertPathBuilderException, InvalidKeyException, SignatureException, CertificateException {
        String str00 = "04660520F9DD45F89DCF103E6355ACCCA9AA237DD09BDFD8AFC18DF391080AA10832FFF4851A6722870FD51103C43875007C735D4B411DE3427442616C4C99134B2C8A8AADCC987605C60E4BB5B491B2941B35067FB912E9A82EAA6F8B9233C651F7D69800C664";
        System.out.println(Hex.toHexString(changeC1C3C2ToC1C2C3(ByteUtil.hexStringToByte(str00))).toUpperCase());
        System.out.println("-------------");
        System.out.println("-------------");
        System.out.println("生成密钥对！");
        KeyPair kp = generateKeyPair();
        System.out.println(Hex.toHexString(kp.getPrivate().getEncoded()));
        System.out.println(Hex.toHexString(kp.getPublic().getEncoded()));
        System.out.println(kp.getPrivate().getAlgorithm());
        System.out.println(kp.getPublic().getAlgorithm());
        System.out.println(kp.getPrivate().getFormat());
        System.out.println(kp.getPublic().getFormat());
        System.out.println("private key d: " + ((BCECPrivateKey)kp.getPrivate()).getD());
        System.out.println("private key d: " + ByteUtil.bytesToHexString(((BCECPrivateKey)kp.getPrivate()).getD().toByteArray()));
        System.out.println("public key q:" + ((BCECPublicKey)kp.getPublic()).getQ());
        System.out.println("public key x:" + ByteUtil.bytesToHexString(((BCECPublicKey)kp.getPublic()).getQ().getAffineXCoord().getEncoded()));
        System.out.println("public key y:" + ByteUtil.bytesToHexString(((BCECPublicKey)kp.getPublic()).getQ().getAffineYCoord().getEncoded()));
        System.out.println("======================================================");
        String str0 = ByteUtil.bytesToHexString(((BCECPublicKey)kp.getPublic()).getQ().getEncoded(true));
        PublicKey publicKey10 = getPublickey(Hex.decode(str0));
        System.out.println("public key xx:" + ByteUtil.bytesToHexString(((BCECPublicKey)publicKey10).getQ().getAffineYCoord().getEncoded()));
        PublicKey publicKey2 = kp.getPublic();
        PrivateKey privateKey2 = kp.getPrivate();
        byte[] bs0 = sm2Encrypt("sunbing".getBytes(), publicKey2);
        System.out.println(Hex.toHexString(bs0));
        bs0 = sm2Decrypt(bs0, privateKey2);
        System.out.println(new String(bs0));
        System.out.println("======================================================");
        BigInteger d = new BigInteger("07656550C62AB2468A81A18AB7ECBE903BCB98A66267C5692451C3947859636C", 16);
        BCECPrivateKey bcecPrivateKey = getPrivatekeyFromD(d);
        PublicKey publicKey1 = getPublickeyFromXY(new BigInteger("613CBEA6FC83EB5A7DDA683D558A07B172A0CBF1F643506E1E59321729166854", 16), new BigInteger("CA7A658757003F4E1057EF70439684F216D62B98D31280B0F48AEDAC0620E443", 16));
        byte[] bs = sm2Encrypt("abc".getBytes(), publicKey1);
        System.out.println(Hex.toHexString(bs).toUpperCase());
        System.out.println(Hex.toHexString(changeC1C3C2ToC1C2C3(bs)).toUpperCase());
        bs = sm2Decrypt(bs, bcecPrivateKey);
        System.out.println(new String(bs));
        System.out.println("======================================================");
        System.out.println("生成数字签名！");
        byte[] msg = "message digest".getBytes();
        byte[] userId = "userId".getBytes();
        byte[] sig = signSm3WithSm2(msg, userId, kp.getPrivate());
        System.out.println(Hex.toHexString(sig));
        System.out.println(verifySm3WithSm2(msg, userId, sig, kp.getPublic()));
        System.out.println("======================================================");
        BigInteger d0 = new BigInteger("097b5230ef27c7df0fa768289d13ad4e8a96266f0fcb8de40d5942af4293a54a", 16);
        BCECPrivateKey bcecPrivateKey0 = getPrivatekeyFromD(d0);
        System.out.println(bcecPrivateKey.getParameters());
        System.out.println(Hex.toHexString(bcecPrivateKey.getEncoded()));
        System.out.println(bcecPrivateKey.getAlgorithm());
        System.out.println(bcecPrivateKey.getFormat());
        System.out.println(bcecPrivateKey.getD());
        System.out.println(bcecPrivateKey instanceof ECPrivateKey);
        System.out.println(bcecPrivateKey instanceof org.bouncycastle.jce.interfaces.ECPrivateKey);
        System.out.println(bcecPrivateKey.getParameters());

//        try {
//            X500Principal iss = new X500Principal("CN=www.xyhn.gov.cn,OU=xxzx,C=CN,S=henan,O=xyhn");
//            ContentSigner sigGen = (new JcaContentSignerBuilder("SM3withSM2")).setProvider("BC").build(kp.getPrivate());
//            X509v3CertificateBuilder certGen = (new JcaX509v3CertificateBuilder(iss, BigInteger.valueOf(1L), new Date(System.currentTimeMillis()), DateTimeUtil.getStrToDate("2030-01-01", "yyyy-MM-dd"), new X500Principal("CN=user"), kp.getPublic())).addExtension(new ASN1ObjectIdentifier("2.5.29.15"), true, new X509KeyUsage(254)).addExtension(new ASN1ObjectIdentifier("2.5.29.37"), true, new DERSequence(KeyPurposeId.anyExtendedKeyUsage)).addExtension(new ASN1ObjectIdentifier("2.5.29.17"), true, new GeneralNames(new GeneralName[]{new GeneralName(1, "admin@xyhn.gov.cn"), new GeneralName(2, "xyhn.gov.cn")}));
//            X509Certificate cert = (new JcaX509CertificateConverter()).setProvider("BC").getCertificate(certGen.build(sigGen));
//            cert.checkValidity(new Date());
//            cert.verify(kp.getPublic());
//            ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded());
//            CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC");
//            cert = (X509Certificate)fact.generateCertificate(bIn);
//            saveFile("E:\\idea_data_sj\\custCert.cer", cert.getEncoded());
//        } catch (OperatorCreationException var26) {
//            var26.printStackTrace();
//        }

        PublicKey publicKey = getPublickeyFromX509File(new File("E:\\idea_data_sj\\custCert.cer"));
        System.out.println("::::" + publicKey);
        PublicKey publicKey3 = getPublickeyFromXY(new BigInteger("59cf9940ea0809a97b1cbffbb3e9d96d0fe842c1335418280bfc51dd4e08a5d4", 16), new BigInteger("9a7f77c578644050e09a9adc4245d1e6eba97554bc8ffd4fe15a78f37f891ff8", 16));
        System.out.println(publicKey3);
        System.out.println(publicKey3.equals(publicKey3));
        System.out.println(publicKey3.getEncoded().equals(publicKey3.getEncoded()));
        System.out.println("======================================================");
        System.out.println("sm3");
        System.out.println(ByteUtil.bytesToHexString(sm3(ByteUtil.hexStringToByte("49204C6F766520596F75"))));
        System.out.println(ByteUtil.bytesToHexString(sm3("123456".getBytes())));
    
        System.out.println(sm3("gdfgfdgrtgdfgfdg"));
        System.out.println("======================================================");
        byte[] plain = Hex.decode("FEDCBA98765432100123456789ABCDEFAACC");
        byte[] key = Hex.decode("0123456789ABCDEFFEDCBA9876543210");
        byte[] cipher = Hex.decode("595298c7c6fd271f0402f804c33d3f66");
        byte[] bs4 = sm4Encrypt(key, plain);
        System.out.println(Hex.toHexString(bs4));
        bs4 = sm4Decrypt(key, bs4);
        System.out.println(Hex.toHexString(bs4));
        System.out.println("--------------------------------------------------");
        String key0 = "我是一个兵";
        String s0 = sm4Encrypt(key0, "天下太平！！！！");
        System.out.println(s0);
        String s1 = sm4Decrypt(key0, s0);
        System.out.println(s1);
    }

    public static void saveFile(String path, byte[] data) {
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(path);
            fileOutputStream.write(data);
            fileOutputStream.flush();
            fileOutputStream.close();
        } catch (Exception var3) {
            var3.printStackTrace();
        }

    }

    static {
        ecDomainParameters = new ECDomainParameters(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
        ecParameterSpec = new ECParameterSpec(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
        if (Security.getProvider("BC") == null) {
            Security.addProvider(new BouncyCastleProvider());
        }

        p = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16);
        a = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", 16);
        b = new BigInteger("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16);
        xg = new BigInteger("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16);
        yg = new BigInteger("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16);
        n = new BigInteger("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16);
        random = new SecureRandom();
    }
}
